import django.utils.timezone
from datetime import timedelta
from django.db.models.signals import post_save
from django.utils.translation import gettext_lazy as _
from django.dispatch import receiver

import logging

from django.db import models
from django.contrib.postgres import fields
import tsl_backend.users.models as users
import tsl_backend.frontend_api.models.route as routes
import tsl_backend.frontend_api.models.workorder as workorders


class WorkerActionRecord(models.Model):
    class Meta:
        db_table = "worker_action_record"
        ordering = ['pk']

    time = models.DateTimeField(auto_now_add=True)
    action = models.IntegerField(choices=[
        (1, "Start"),
        (2, "Pause"),
        (3, "Complete"),
    ])
    worker_record = models.ForeignKey("WorkerRecord", on_delete=models.PROTECT)  

    def formatted_time(self):
        if self.time:
            return self.time.strftime("%Y.%m.%d %H:%M:%S")
        else:
            return None

class WorkerRecord(models.Model):
    class Meta:
        db_table = "worker_record"

    account = models.ForeignKey(users.Account, on_delete=models.PROTECT, null=True)
    # action_record = models.ForeignKey(WorkerActionRecord, on_delete=models.PROTECT, null=True)
    work_duration = models.DurationField(default=timedelta()) #increase per every work duration, for reporting
    work_count = models.IntegerField(default=0)  #increase per every fail qc, for reporting
    pause_duration = models.DurationField(default=timedelta()) #increase per every pause duration, for reporting
    # status = models.IntegerField(choices=[
    #     (1, "Open"),
    #     (2, "In Progress"),
    #     (3, "Complete"),
    # ], default=1)
    def get_work_duration_in_hour(self):
        hours = self.work_duration.total_seconds() / 3600
        return "{:.2f}小时".format(hours)


class QcFailedReason(models.Model):
    class Meta:
        db_table = "qc_failed_reason"
        verbose_name = '不合格原因'
        verbose_name_plural = '不合格原因'

    reason = models.CharField(max_length=100, verbose_name="原因")
    unit = models.CharField(max_length=100, null=True, verbose_name="单位")
    flow = models.ForeignKey(users.Flow, on_delete=models.PROTECT, verbose_name="工艺节点")
    role = models.ManyToManyField(users.Role, verbose_name="角色")

    def __str__(self):
        return self.reason


class QcFailed(models.Model):
    class Meta:
        db_table = "qc_failed"

    reason = models.ForeignKey(QcFailedReason, on_delete=models.PROTECT)
    quantity = models.IntegerField()


class CheckRecord(models.Model):
    class Meta:
        db_table = "check_record"

    account = models.ForeignKey(users.Account, on_delete=models.PROTECT, null=True)
    check_type = models.IntegerField(choices=[
        (1, "QC"),
        (2, "Leader"),
        (3, "Stone"),
    ])
    received_at = models.DateTimeField(null=True)
    check_at = models.DateTimeField(null=True)
    work_count = models.IntegerField(default=0)
    failed = models.BooleanField(null=True)
    failed_details = models.ManyToManyField(QcFailed)
    remark = models.CharField(max_length=255, null=True, blank=True)

    def formatted_received_at(self):
        if self.received_at:
            return self.received_at.strftime("%Y.%m.%d %H:%M:%S")
        else:
            return None
        
    
    def formatted_check_at(self):
        if self.check_at:
            return self.check_at.strftime("%Y.%m.%d %H:%M:%S")
        else:
            return None
        

# Record for one complete round of a flow.
class Record(models.Model):
    class Meta:
        ordering=["pk"]
        
    time = models.DateTimeField(default=django.utils.timezone.now)
    worker = models.ForeignKey(WorkerRecord, on_delete=models.PROTECT, null=True)
    qc_check = models.ForeignKey(CheckRecord, on_delete=models.PROTECT, related_name='qc_check', null=True)
    leader_check = models.ForeignKey(CheckRecord, on_delete=models.PROTECT, related_name='leader_check', null=True)
    # qc_handler_account = models.ForeignKey(users.Account, on_delete=models.PROTECT, related_name='qc_handler_account', null=True)
    # qc_handler_time = models.DateTimeField(null=True)
    # worker_handler_account = models.ForeignKey(users.Account, on_delete=models.PROTECT, null=True)
    # worker_handler_time = models.DateTimeField(null=True)
    stone_check = models.ForeignKey(CheckRecord, on_delete=models.PROTECT, related_name='stone_check', null=True)

    route_detail = models.ForeignKey("RouteDetail", on_delete=models.PROTECT)

    def formatted_time(self):
        if self.time:
            return self.time.strftime("%Y.%m.%d %H:%M:%S")
        else:
            return None
        
class ProductionRemark(models.Model):
    class Meta:
        db_table = "production_remark"
        verbose_name = '生产备注'
        verbose_name_plural = '生产备注'

    type = models.CharField(max_length=255, choices=[("INT", "INT"),("BOOL","BOOL")])
    remark = models.CharField(max_length=255)
    # comment = models.CharField(max_length=255)
    # ans = models.PositiveSmallIntegerField(null=True, blank=True)

    def __str__(self):
        return f"{self.remark}"

class Dispatcher(models.Model):
    start_at = models.DateTimeField(null=True)
    start_account = models.ForeignKey(users.Account, on_delete=models.PROTECT, related_name='start_count', null=True)
    start_weights = models.JSONField(null=True)   #TODO: to be deleted
    end_at = models.DateTimeField(null=True)
    end_account = models.ForeignKey(users.Account, on_delete=models.PROTECT, related_name='end_count', null=True)
    end_weights = models.JSONField(null=True)   #TODO: to be deleted
    centersender = models.CharField(max_length=100, blank=True, null=True)

    def formatted_start_at(self):
        if self.start_at:
            return self.start_at.strftime("%Y.%m.%d %H:%M:%S")
        else:
            return None
        

    def formatted_end_at(self):
        if self.end_at:
            return self.end_at.strftime("%Y.%m.%d %H:%M:%S")
        else:
            return None


class OrderRouting(models.Model):
    class Meta:
        db_table = "order_routing"

    workorder = models.OneToOneField(workorders.Detail, on_delete=models.PROTECT)
    holder = models.ForeignKey(users.Account, on_delete=models.PROTECT, related_name='holder', null=True)
    holder_record_time = models.DateTimeField(null=True)

    order_complete_date = models.DateTimeField(null=True)

    # flow_report = models.IntegerField()
    # detail = models.ForeignKey(RouteDetail, on_delete=models.PROTECT)
    # production_remark = models.ManyToManyField(ProductionRemark)
    # production_remark_ans = models.PositiveSmallIntegerField(blank=True, null=True)

    def __str__(self):
        return f"{self.workorder.order}"


    def formatted_holder_record_time(self):
        if self.holder_record_time:
            return self.holder_record_time.strftime("%Y.%m.%d %H:%M:%S")
        else:
            return None
        
    def formatted_order_complete_date(self):
        if self.order_complete_date:
            return self.order_complete_date.strftime("%Y.%m.%d %H:%M:%S")
        else:
            return None
        
class ProductionRemarkAns(models.Model):
    prod_remark = models.ForeignKey(ProductionRemark, on_delete=models.PROTECT)
    production_remark_ans = models.PositiveSmallIntegerField(default=0)
    order_routing = models.ForeignKey(OrderRouting, on_delete=models.CASCADE)

class RouteDetail(models.Model):

    class StatusChoices(models.IntegerChoices):
        Open = 1, _("Open")
        In_Progress = 2, _("In Progress")
        Complete = 3, _("Complete")
    # STATUS_CHOICES=[
    #     (1, "Open"),
    #     (2, "In Progress"),
    #     (3, "Complete"),
    # ]
    class Meta:
        ordering = ["pk"]

    flow = models.ForeignKey(users.Flow, on_delete=models.PROTECT)
    dispatcher = models.OneToOneField(Dispatcher, on_delete=models.PROTECT, null=True)
    # record = models.ManyToManyField(Record)
    quantity = models.IntegerField(null=True)
    difficulty = models.ForeignKey(routes.Difficulty, on_delete=models.PROTECT, null=True)
    primary_stone_setting = models.ForeignKey(routes.StoneMountSetting, on_delete=models.PROTECT, related_name='order_primary_stone_mount_setting', null=True)
    secondary_stone_setting = models.ForeignKey(routes.StoneMountSetting, on_delete=models.PROTECT, related_name='order_secondary_stone_setting', null=True)
    consumption_percentage = models.DecimalField(max_digits=8, decimal_places=3, null=True)
    worker_fee = models.DecimalField(max_digits=8, decimal_places=3, null=True)
    status = models.IntegerField(choices=StatusChoices.choices, default=1)

    seq = models.PositiveSmallIntegerField()
    order_route = models.ForeignKey(OrderRouting, on_delete=models.PROTECT)

class ActualWeight(models.Model):
    actual_weight = models.DecimalField(max_digits=8, decimal_places=3, null=True, default=0)
    article = models.CharField(max_length=30, blank=True, default="")
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    route_detail = models.ForeignKey(RouteDetail, on_delete=models.CASCADE, related_name='actual_weight')
    state = models.PositiveSmallIntegerField(default=1)
    # 0 -工人交收發
    # 1 -收發交工人
    # 2 - PF
    # 3 - A/B 單

# method for updating
@receiver(post_save, sender=OrderRouting)
def create_production_remark_ans(sender, instance, created, **kwargs):
    if created:
        prod_remark_objs=ProductionRemark.objects.all()
        for prod_remark_obj in prod_remark_objs:
            prod_remark_ans_obj, _created = ProductionRemarkAns.objects.update_or_create(prod_remark=prod_remark_obj,
                                                                                                order_routing=instance)
            
            logging.info(f"create production remark {prod_remark_obj} for route_detail {instance}")
